package com.dhcc.sds.custom.function;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.dhcc.cdc.busi.dao.CdcEpisodeMapper;
import com.dhcc.cdc.busi.dao.CdcSurgeryMapper;
import com.dhcc.cdc.busi.entity.CdcDictionaryEntity;
import com.dhcc.cdc.busi.entity.CdcEpisodeEntity;
import com.dhcc.cdc.busi.entity.CdcSurgeryEntity;
import com.dhcc.cdc.busi.service.ICdcDictionaryService;
import com.dhcc.cdc.busi.service.ICdcEpisodeService;
import com.dhcc.cdc.sys.dao.DictionaryMapper;
import com.dhcc.cdc.sys.entity.DictionaryEntity;
import com.dhcc.core.framework.util.CommonUtil;
import com.dhcc.core.framework.util.DateUtil;
import com.dhcc.core.framework.util.SpringContextHolder;
import com.dhcc.sds.base.dao.SdsFunctionMapper;
import com.dhcc.sds.base.entity.SdsQcentityRuleEntity;
import com.dhcc.sds.base.service.ISdsQcentityRuleService;
import com.dhcc.sds.busi.entity.SdsQcincaseEntity;
import com.dhcc.sds.busi.entity.SdsQcincaseOperlogEntity;
import com.dhcc.sds.custom.entity.SdsCusIndexFieldEntity;
import com.dhcc.sds.custom.entity.SdsCusMrlistEntity;
import com.dhcc.sds.custom.entity.SdsCusMrlistOperlogEntity;
import com.dhcc.sds.custom.service.ISdsCusMrlistOperlogService;
import com.dhcc.sds.custom.service.ISdsCusMrlistService;
import com.dhcc.sds.standard.dao.SdsStandDicMatchMapper;
import com.dhcc.sds.standard.dao.SdsStandSourceMapper;
import com.dhcc.sds.standard.entity.SdsStandSourceEntity;
import com.dhcc.sds.standard.service.ISdsStandDicService;
import org.apache.commons.lang.text.StrSubstitutor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.text.DecimalFormat;
import java.util.*;

@Component("getValueCusSrv")
public class GetValueCus {
    static DictionaryMapper dictionaryMapper = SpringContextHolder.getBean("dictionaryMapper");
    static CdcEpisodeMapper cdcEpisodeMapper = SpringContextHolder.getBean("cdcEpisodeMapper");
    static SdsStandSourceMapper sdsStandSourceMapper = SpringContextHolder.getBean("sdsStandSourceMapper");
    static CdcSurgeryMapper cdcSurgeryMapper = SpringContextHolder.getBean("cdcSurgeryMapper");
    static ISdsCusMrlistService sdsCusMrlistService = SpringContextHolder.getBean("sdsCusMrlistService");
    static ISdsCusMrlistOperlogService sdsCusMrlistOperlogService = SpringContextHolder.getBean("sdsCusMrlistOperlogService");
    static ISdsQcentityRuleService sdsQcentityRuleService = SpringContextHolder.getBean("sdsQcentityRuleService");
    static ICdcEpisodeService cdcEpisodeService = SpringContextHolder.getBean("cdcEpisodeService");
    static SdsFunctionMapper sdsFunctionMapper = SpringContextHolder.getBean("sdsFunctionMapper");
    static ICdcDictionaryService cdcDictionaryService = SpringContextHolder.getBean("cdcDictionaryService");
    static SdsStandDicMatchMapper sdsStandDicMatchMapper = SpringContextHolder.getBean("sdsStandDicMatchMapper");
    static ISdsStandDicService sdsStandDicService = SpringContextHolder.getBean("sdsStandDicService");

    public Object Episode(Long episodeId, Long entityId, Long datasourceId, Integer currentTime, Long dicId, Long valueTime) {
        String res = "N";
        List<Map<String, Object>> ressonList = new ArrayList<>();
        SdsStandSourceEntity source = sdsStandSourceMapper.selectById(datasourceId);
        if (!CommonUtil.isEmpty(source)) {
            CdcEpisodeEntity cdcEpisodeEntity = cdcEpisodeService.selectById(episodeId);
            String sourceCode = source.getSourceCode();
            switch (sourceCode) {
                case "isDeath":
                    Integer isDeath = cdcEpisodeEntity.getIsDeath();
                    if (isDeath==1){
                        res = "Y";
                    }
                    Map<String, Object> map = new HashMap<>();
                    map.put("isDeath", res);
                    ressonList.add(map);
                    break;
            }
        }
        return ressonList;
    }

    /**
     * 获取病人HIS数据-医嘱信息
     */
    public Object Ordexec(Long episodeId, Long datasourceId, Integer currentTime, Long dicId, Long valueTime) {
        List<List<Map<String, Object>>> resultList = new ArrayList<>();
        SdsStandSourceEntity source = sdsStandSourceMapper.selectById(datasourceId);
        if (!StringUtils.isEmpty(source)) {
            String sourceCode = source.getSourceCode();
            // 采集时机, 获取取值条件
            String sqlStr = this.calcGetExecTiming(episodeId, valueTime);
            if (!StringUtils.isEmpty(dicId)) {
                // 查询标准项关联医嘱
                List<Long> ordMastList = sdsStandDicMatchMapper.selectMatchOrderId(dicId);
                // 查找子节点关联医嘱
                //查找子节点
                List<Long> dicChildrenIds = sdsStandDicService.getRootChildren(dicId);
                for (Long dicChildrenId : dicChildrenIds) {
                    ordMastList.addAll(sdsStandDicMatchMapper.selectMatchOrderId(dicChildrenId));
                }
                if (ordMastList.isEmpty()) {
                    return resultList;
                }
                // 去重
                Set<Long> ordMastSet = new HashSet(ordMastList);
                ordMastList = new ArrayList(ordMastSet);
                List<Map<String, Object>> execList = sdsFunctionMapper.selectOrdExec(episodeId, null, ordMastList, sqlStr);
                if (!execList.isEmpty()) {
                    resultList.add(execList);
                }
            }
        }
        return resultList;
    }

    /**
     * 获取病人电子病历-住病案首页费用信息
     */
    public Object EprFeeInfo(Long episodeId, Long entityId, Long datasourceId, Integer currentTime, Long dicId, Long valueTime) {
        List<Map<String, Object>> ressonList = new ArrayList<>();
        Object resultVal = "";

        SdsStandSourceEntity source = sdsStandSourceMapper.selectById(datasourceId);
        List<Map<String, Object>> result = new ArrayList<>();
        if (!StringUtils.isEmpty(source)) {
            String sourceCode = source.getSourceCode();
            Map<String,Object> param = new HashMap<>();
            param.put("episodeId", episodeId);
            Map<String,Object> feeMap = sdsFunctionMapper.getFeeByType(param);
            if (CommonUtil.isNotEmpty(feeMap)) {
                if (CommonUtil.isNotEmpty(feeMap.get(sourceCode))) {
                    String feeValue = feeMap.get(sourceCode).toString();
                    //处理精度，小数点后两位
                    DecimalFormat df = new DecimalFormat("0.00");
                    resultVal = df.format(Float.parseFloat(feeValue));
                    if (CommonUtil.isNotEmpty(resultVal)) {
                        Map<String, Object> map = new HashMap<>();
                        map.put(sourceCode, resultVal);
                        map.put("id", "0");
                        ressonList.add(map);
                    }
                }
            }
        }
        return ressonList;
    }

    public Object SdsIntheInfo(Long episodeId, Long entityId, Long datasourceId, Integer currentTime, Long dicId, Long valueTime) {
        List<Map<String, Object>> ressonList = new ArrayList<>();
        SdsStandSourceEntity source = sdsStandSourceMapper.selectById(datasourceId);
        if (!StringUtils.isEmpty(source)) {
            String sourceCode = source.getSourceCode();
            if ("intheReason".equals(sourceCode)) {
                // 查询入组记录
                SdsCusMrlistEntity sdsCusMrlistEntity = sdsCusMrlistService.selectOne(new EntityWrapper<SdsCusMrlistEntity>().eq("episode_id", episodeId).in("state", "I"));
                Wrapper<SdsCusMrlistOperlogEntity> wpr = new EntityWrapper<>();
                wpr.eq("in_case_id", sdsCusMrlistEntity.getId()).eq("oper_state", "I");
                SdsCusMrlistOperlogEntity sdsCusMrlistOperlogEntity = sdsCusMrlistOperlogService.selectOne(wpr);
                String reasonStr = sdsCusMrlistOperlogEntity.getOperReason();
                String[] reasonArr = reasonStr.split(",");
                for (String ruleId : reasonArr) {
                    SdsQcentityRuleEntity rule = sdsQcentityRuleService.selectById(ruleId);
                    Map<String, Object> map = new HashMap<>();
                    map.put("intheReason", rule.getRuleDesc());
                    ressonList.add(map);
                }
            }else if ("InCaseOrNot".equals(sourceCode)) {
                String res = "N";
                Wrapper<SdsCusMrlistEntity> inCaseWrp = new EntityWrapper<>();
                inCaseWrp.eq("episode_id",episodeId).eq("state","I");
                List<SdsCusMrlistEntity> sdsCusMrlistEntities = sdsCusMrlistService.selectList(inCaseWrp);
                if (sdsCusMrlistEntities.size()==0) return res;
                for (SdsCusMrlistEntity sdsCusMrlistEntity : sdsCusMrlistEntities) {
                    if (sdsCusMrlistEntity.getEntityId().equals(entityId)) {
                        res = "Y";
                        break;
                    }
                }
                Map<String, Object> map = new HashMap<>();
                map.put("InCaseOrNot", res);
                ressonList.add(map);
            }
        }
        return ressonList;
    }

    private String calcGetExecTiming(Long episodeId, Long valueTime) {
        String sqlStr = "";
        String filterSqlByDate = "AND oe.bus_order_priority_id <> ${priorityId} AND (oe.first_exec_date BETWEEN str_to_date('${sTime}','%Y-%m-%d %H:%i:%s') AND str_to_date('${eTime}', '%Y-%m-%d %H:%i:%s') OR oe.start_date BETWEEN str_to_date('${sTime}','%Y-%m-%d %H:%i:%s') AND str_to_date('${eTime}', '%Y-%m-%d %H:%i:%s'))";
        String filterSqlByAsc = "AND oe.bus_order_priority_id <> ${priorityId} ORDER BY IF(ISNULL(oe.first_exec_date),1,0) ${seqType}, oe.start_date ${seqType}";
        String filterSqlByDesc = "AND oe.bus_order_priority_id <> ${priorityId} ORDER BY IF(ISNULL(oe.last_exec_date),0,1) ${seqType}, oe.start_date ${seqType}";
        String filterSqlByPriority = "AND oe.bus_order_priority_id = ${priorityId} ORDER BY oe.start_date ${seqType}";
        String filterSqlByInstruc = "AND oe.bus_order_instruc_id = ${instrucId} ORDER BY oe.start_date ${seqType}";
        String seqType = "";
        Long priorityId = 0L;
        Long instrucId = 0L;
        Long tmpTime = 0L;
        String fTime = "";
        String tTime = "";

        // 出院带药 bus_order_priority:OUT
        CdcDictionaryEntity cdcDictionaryEntity = cdcDictionaryService.queryByTypeCodeAndCode("OrdData", "bus_order_priority", "OUT");
        if (!StringUtils.isEmpty(cdcDictionaryEntity)) {
            priorityId = cdcDictionaryEntity.getId();
        }

        // 如果没有配置采集时机，默认入院首次
        if (CommonUtil.isEmpty(valueTime)) {
            Map<String, Object> map = new HashMap<>();
            map.put("seqType", "ASC");
            map.put("priorityId", priorityId);
            StrSubstitutor strSubstitutor = new StrSubstitutor(map);
            sqlStr = strSubstitutor.replace(filterSqlByAsc);
            return sqlStr;
        }
        // 获取采集时间描述
        DictionaryEntity getTimingDic = dictionaryMapper.selectById(valueTime);
        String getType = getTimingDic.getCode();
        // 如果采集时机包含手术，则先取手术开始、结束时间
        if (getType.contains("Oper")) {
            Wrapper<CdcSurgeryEntity> operWpr = new EntityWrapper<>();
            operWpr.eq("episode_id", episodeId).eq("is_active", 1).orderBy("start_date");
            List<CdcSurgeryEntity> operList = cdcSurgeryMapper.selectList(operWpr);
            if (operList.size() == 0) {
                return "";
            }
            // 只取首次手术
            Date startDate = DateUtil.parse("1900-01-01 00:00:00");
            Date endDate = DateUtil.parse("1900-01-01 00:00:00");
            switch (getType) {
                case "BfOper":
                    for (CdcSurgeryEntity oper : operList) {
                        if (oper.getStartDate() != null || oper.getEndDate() != null) {
                            startDate = oper.getStartDate();
                            break;
                        }
                    }
                    // 术前，默认手术前0.5-1小时
                    tmpTime = startDate.getTime();
                    fTime = DateUtil.getTime(new Date(tmpTime - 3600 * 1000));
                    tTime = DateUtil.getTime(new Date(tmpTime - 1800 * 1000));
                    sqlStr = filterSqlByDate;
                    break;
                case "InOper":
                    for (CdcSurgeryEntity oper : operList) {
                        if (oper.getStartDate() != null && oper.getEndDate() != null) {
                            startDate = oper.getStartDate();
                            endDate = oper.getEndDate();
                            break;
                        }
                    }
                    // 术中
                    fTime = DateUtil.getTime(startDate);
                    tTime = DateUtil.getTime(endDate);
                    sqlStr = filterSqlByDate;
                    break;
                case "AfOper":
                    for (CdcSurgeryEntity oper : operList) {
                        if (oper.getStartDate() != null || oper.getEndDate() != null) {
                            endDate = oper.getEndDate();
                            break;
                        }
                    }
                    // 术后，默认手术后72小时
                    tmpTime = endDate.getTime();
                    fTime = DateUtil.getTime(endDate);
                    tTime = DateUtil.getTime(new Date(tmpTime + 3 * 24 * 3600 * 1000));
                    sqlStr = filterSqlByDate;
                    break;
                case "AllOper":
                    for (CdcSurgeryEntity oper : operList) {
                        if (oper.getStartDate() != null || oper.getEndDate() != null) {
                            startDate = oper.getStartDate();
                            endDate = oper.getEndDate();
                            break;
                        }
                    }
                    //围术期
                    tmpTime = startDate.getTime();
                    fTime = DateUtil.getTime(new Date(tmpTime - 3600 * 1000));
                    tmpTime = endDate.getTime();
                    tTime = DateUtil.getTime(new Date(tmpTime + 3 * 24 * 3600 * 1000));
                    sqlStr = filterSqlByDate;
                    break;
                case "WithOperRoom":
                    // 带手术室 bus_order_instruc:1
                    CdcDictionaryEntity cdcDictionaryEntity2 = cdcDictionaryService.queryByTypeCodeAndCode("OrdData", "bus_order_instruc", "1");
                    if (!StringUtils.isEmpty(cdcDictionaryEntity2)) {
                        instrucId = cdcDictionaryEntity2.getId();
                    }
                    seqType = "ASC";
                    sqlStr = filterSqlByInstruc;
                    break;
            }
        } else {
            // 获取就诊时间
            CdcEpisodeEntity admObj = cdcEpisodeMapper.selectById(episodeId);
            Date admDate = admObj.getAdmDate();
            Date dishDate = admObj.getDishDate();
            switch (getType) {
                case "Emergency":
                    // 急诊, 默认早于入院时间
                    tmpTime = admDate.getTime();
                    fTime = DateUtil.getTime(new Date(tmpTime - 24 * 3600 * 1000));
                    tTime = DateUtil.getTime(new Date(tmpTime));
                    sqlStr = filterSqlByDate;
                    break;
                case "LastInHosp":
                    // 住院末次
                    seqType = "DESC";
                    sqlStr = filterSqlByDesc;
                    break;
                case "EMR-Inhos24":
                    // 急诊/入院24小时
                    tmpTime = admDate.getTime();
                    fTime = DateUtil.getTime(admDate);
                    tTime = DateUtil.getTime(new Date(tmpTime + 24 * 3600 * 1000));
                    sqlStr = filterSqlByDate;
                    break;
                case "EMR-Inhos7day":
                    // 入院一周
                    tmpTime = admDate.getTime();
                    fTime = DateUtil.getTime(admDate);
                    tTime = DateUtil.getTime(new Date(tmpTime + 24 * 3600 * 1000 * 7));
                    sqlStr = filterSqlByDate;
                    break;
                case "DishHosMedi":
                    seqType = "ASC";
                    sqlStr = filterSqlByPriority;
                    break;
                case "LongOrder":
                    // 长期医嘱 bus_order_priority:S
                    CdcDictionaryEntity cdcDictionaryEntity1 = cdcDictionaryService.queryByTypeCodeAndCode("OrdData", "bus_order_priority", "S");
                    if (!StringUtils.isEmpty(cdcDictionaryEntity1)) {
                        priorityId = cdcDictionaryEntity1.getId();
                    }
                    seqType = "ASC";
                    sqlStr = filterSqlByPriority;
                    break;
                case "DurHosp":
                    // 住院期间 医嘱日期范围为住院期间
                    fTime = DateUtil.getTime(admDate);
                    tTime = DateUtil.getTime(dishDate);
                    sqlStr = filterSqlByDate;
                    break;
                default:
                    // 默认入院首次
                    seqType = "ASC";
                    sqlStr = filterSqlByAsc;
                    break;
            }
        }
        Map<String, Object> map = new HashMap<>();
        map.put("sTime", fTime);
        map.put("eTime", tTime);
        map.put("seqType", seqType);
        map.put("priorityId", priorityId);
        map.put("instrucId", instrucId);
        StrSubstitutor strSubstitutor = new StrSubstitutor(map);
        sqlStr = strSubstitutor.replace(sqlStr);
        return sqlStr;
    }
}
